package engine.core.scene;

import java.util.ArrayList;

import engine.gameObject.GameObject;
import engine.shader.Shader;

public class SphereTree {
	
	private GameObject root;
	
	//states, if this sphere tree is already initialized
	private boolean initialized;
	
	public SphereTree(Scene scene) {
		root = new GameObject() {
			//empty gameobject
		};
		root.setId("root");
		root.setScene(scene);
	}
	
	public void init() {
		root.initAbs();
		
		initialized = true;
	}
	
	public void addGameObject(GameObject gameObject) {
		root.addChild(gameObject);
		
		if(initialized) {
			gameObject.initAbs();
		}
	}
	
	public void removeGameObject(GameObject gameObject) {
		root.removeChild(gameObject);
	}
	
	public GameObject find(String id) {
		return findRec(id, root);
	}
	
	private GameObject findRec(String id, GameObject gameObject) {
		if(gameObject.getId() != null && gameObject.getId().equals(id)) {
			return gameObject;
		} else {
			GameObject g = null;
			
			for(GameObject child: gameObject.getChildren()) {
				g = findRec(id, child);
				
				if(g != null) {
					break;
				}
			}
			
			return g;
		}
	}
	
	public ArrayList<GameObject> findAll(String id, ArrayList<GameObject> result) {
		findAllRec(id, root, result);
		
		return result;
	}
	
	private void findAllRec(String id, GameObject gameObject, ArrayList<GameObject> result) {
		if(gameObject.getId() != null && gameObject.getId().equals(id)) {
			result.add(gameObject);
		}
		
		for(GameObject child: gameObject.getChildren()) {
			findAllRec(id, child, result);
		}
	}
	
	public void render(Frustum frustum, Shader shader) {
		root.renderAbs(frustum, shader);
	}
	
	public void update(float timeElapsed) {
		root.updateAbs(timeElapsed);
	}

	public void keyPressed(int key) {
		root.keyPressedAbs(key);
	}

	public void keyReleased(int key) {
		root.keyReleasedAbs(key);
	}

	public void mousePressed(int posX, int posY, int button) {
		root.mousePressedAbs(posX, posY, button);
	}

	public void mouseReleased(int posX, int posY, int button) {
		root.mouseReleasedAbs(posX, posY, button);
	}

	public void mouseMoved(int posX, int posY, int button) {
		root.mouseMovedAbs(posX, posY, button);
	}

	public void mouseDragged(int posX, int posY, int button) {
		root.mouseDraggedAbs(posX, posY, button);
	}

	public void mouseWheelMoved(int movement) {
		root.mouseWheelMovedAbs(movement);
	}
	
	public boolean checkCollision(GameObject other) {
		for(GameObject g: root.getChildren()) {
			if(g.checkCollision(other)) {
				return true;
			}
		}
		
		return false;
	}
}
